#include "SerialCommunication.h"






int SerialInit(char *dev)
{
    int fdSerial = -1;
    fdSerial = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
    if(fdSerial < 0)
    {
        COMLOG_ERROR_LOG("open serial error , dev name :%s\n", dev);;
        return -1;
    }
    return fdSerial;
}



int SerialSend(int serialfd, char *data, int datalen )
{
    size_t ret = 0;

    ret = write(serialfd, data, datalen);
    if (ret == datalen)
    {
        COMLOG_INFO_LOG("send data is %s\n successed", data);
        return ret;
    }
    else
    {
        COMLOG_ERROR_LOG("write device error\n");
        tcflush(serialfd,TCOFLUSH); //清空发送缓冲区 TCIFLUSH 清空接收缓冲区  TCIOFLUSH 同时清空接收与发送缓冲区
        return -1;
    } 
    return 0;
}


int SerialRev(int serialfd, char *data, int datalen, int mstimeout)
{
    int len = 0, fs_sel = 0;
    fd_set fs_read;
    struct timeval time = {0};

    time.tv_sec = mstimeout / 1000;              //set the rcv wait time
    time.tv_usec = mstimeout % 1000 * 1000;    //100000us = 0.1s

    FD_ZERO(&fs_read);        //每次循环都要清空集合，否则不能检测描述符变化
    FD_SET(serialfd, &fs_read);    //添加描述符

    // 超时等待读变化，>0：就绪描述字的正数目， -1：出错， 0 ：超时
    fs_sel = select(serialfd + 1, &fs_read, NULL, NULL, &time);
    if(fs_sel)
    {
        len = read(serialfd, data, datalen);
        return len;
    }
    else if(0 == fs_sel)
    {
        COMLOG_INFO_LOG("serial read outtime \n");
        return  0;
    }
    else 
    {
        COMLOG_INFO_LOG("serial read error \n");
        return -1;
    }

    return 0;
}


int SerialSetOpt(int serialfd, int baudrate, int databits, int parity, int stopbits)
{
    int fd = serialfd;
    int nBits = databits;
    int nParity = parity;
    int nSpeed = baudrate;
    int nStop = stopbits;
    struct termios newtio = {0}, oldtio = {0};
    struct serial_struct serinfo = {0};
    if (tcgetattr(fd, &oldtio) != 0)
    {
        COMLOG_ERROR_LOG("read serial old attr failed\n");
        return -1;
    }
    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
    switch (nBits)
    {
        case 7:
            newtio.c_cflag |= CS7;
        break;
        case 8:
            newtio.c_cflag |= CS8;
        break;
        default:
            COMLOG_ERROR_LOG("Unsupported data size\n");
            return -1;
    }

    switch (nParity)
    {
        case 'o':
        case 'O':                     //奇校验
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'e':
        case 'E':                     //偶校验
            newtio.c_iflag |= (INPCK | ISTRIP);
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            break;
        case 'n':
        case 'N':                    //无校验
            newtio.c_cflag &= ~PARENB;
            break;
        default:
            COMLOG_ERROR_LOG("Unsupported parity\n");
            return -1;
    }

    switch (nStop)
    {
        case 1:
            newtio.c_cflag &= ~CSTOPB;
        break;
        case 2:
            newtio.c_cflag |= CSTOPB;
        break;
        default:
            COMLOG_ERROR_LOG("Unsupported stop bits\n");
            return -1;
    }

    switch (nSpeed)
    {
        case 2400:
            cfsetispeed(&newtio, B2400);
            cfsetospeed(&newtio, B2400);
            break;
        case 4800:
            cfsetispeed(&newtio, B4800);
            cfsetospeed(&newtio, B4800);
            break;
        case 9600:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
        case 19200:
            cfsetispeed(&newtio, B19200);
            cfsetospeed(&newtio, B19200);
            break;
        case 38400:
            cfsetispeed(&newtio, B38400);
            cfsetospeed(&newtio, B38400);
            break;
        case 57600:
            cfsetispeed(&newtio, B57600);
            cfsetospeed(&newtio, B57600);
            break;
        case 115200:
            cfsetispeed(&newtio, B115200);
            cfsetospeed(&newtio, B115200);
            break;
        case 230400:
            cfsetispeed(&newtio, B230400);
            cfsetospeed(&newtio, B230400);
            break;
        default:
            COMLOG_ERROR_LOG("Unsupported baud rate, set default 9600!\n");
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
    }

    newtio.c_cc[VTIME] = 1;       // 读取一个字符等待1*(1/10)s
    newtio.c_cc[VMIN] = 1;        // 读取字符的最少个数为1

    tcflush(fd,TCIFLUSH);

    if (tcsetattr(fd, TCSANOW, &newtio) != 0)    //激活新设置
    {
          COMLOG_ERROR_LOG("serial set attr error\n");
          return -1;
    }
    COMLOG_INFO_LOG("serial set done\n");
    return 0;
}


int SerailSetRTS(int serialfd, char enable)
{
   int status = 0;
   ioctl(serialfd, TIOCMGET, &status);
   if(1 == enable)
   {
     status |= TIOCM_RTS;
   } 
   else if(0 == enable)
   {
     status &= ~TIOCM_RTS;  
   }
   ioctl(serialfd, TIOCMSET, &status);
   return 0;
}


int SerailSetDTR(int serialfd, char enable)
{

   int status = 0;
   ioctl(serialfd, TIOCMGET, &status);
   if(1 == enable)
   {
     status |= TIOCM_DTR;
   } 
   else if(0 == enable)
   {
     status &= ~TIOCM_DTR;  
   }
   ioctl(serialfd, TIOCMSET, &status);
   return 0;

}